package org.argeproje.resim.proc.histogram;
import java.util.ArrayList;
import java.util.Iterator;

import org.argeproje.resim.DataPlotUT;
import org.argeproje.resim.proc.Processor;
import org.argeproje.resim.proc.data.*;
import org.argeproje.resim.proc.tools.MathUT;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
/*
Definition
  Performs local histogram equalization on image. 
Inputs
  ImageDA
Parameters
  wxh: Width and height of local image segment around pixel on which local histogram
  equalization algorithm is run.
Outputs
  ImageDA
 */
public class StatisticalHistogramPR extends Processor {
	private int _localWidth = 3;
	private int _localHeight = 3;
	private int _intensityMultiplier = 4;
	private float _meanUpperLimit = 0.4F;
	private float _varianceLowerLimit = 0.02F;
	private float _varianceUpperLimit = 0.4F;
	public void setParameters(int localWidth, int localHeight, int multiplier,
			float meanUpperLimit, float varianceLowerLimit, float varianceUpperLimit){
		setParamLocalWidth(localWidth);
		setParamLocalHeight(localHeight);
		setParamIntensityMultiplier(multiplier);
		setParamMeanUpperLimit(meanUpperLimit);
		setParamVarianceLowerLimit(varianceLowerLimit);
		setParamVarianceUpperLimit(varianceUpperLimit);
	}
	public void setParamLocalWidth(int localWidth){
		_localWidth = localWidth;
	}
	public int getParamLocalWidth(){
		return _localWidth;
	}
	public void setParamLocalHeight(int localHeight){
		_localHeight = localHeight;
	}
	public int getParamLocalHeight(){
		return _localHeight;
	}
	public int getParamIntensityMultiplier() {
		return _intensityMultiplier;
	}
	public void setParamIntensityMultiplier(int multiplier) {
		_intensityMultiplier = multiplier;
	}
	public float getParamMeanUpperLimit() {
		return _meanUpperLimit;
	}
	public void setParamMeanUpperLimit(float upperLimit) {
		_meanUpperLimit = upperLimit;
	}
	public float getParamVarianceLowerLimit() {
		return _varianceLowerLimit;
	}
	public void setParamVarianceLowerLimit(float lowerLimit) {
		_varianceLowerLimit = lowerLimit;
	}
	public float getParamVarianceUpperLimit() {
		return _varianceUpperLimit;
	}
	public void setParamVarianceUpperLimit(float upperLimit) {
		_varianceUpperLimit = upperLimit;
	}
	public Data process() {
		
		ImageDA im = new ImageDA(getInputAsImageDA());   
	    int nBand = im.getNBands();
	    ArrayList<ImageSegmentDA> segments = new ArrayList<ImageSegmentDA>();
	    int segmentSize = _localWidth * _localHeight;
	    int centerX = (_localWidth - 1) / 2;
	    int centerY = (_localHeight - 1) / 2;
	    for (int i = 0; i < nBand; i++) {
	    	int maxPixelVal = im.getNBins(i) - 1;
	    	ImageSegmentDA wholeImage = new ImageSegmentDA(im, i, im.getWidth(), im.getHeight(), 0, 0);
	    	float wholeMean = MathUT.getNormalizedMean(wholeImage.getSegmentData(), maxPixelVal);
	    	float wholeVariance = MathUT.getNormalizedVariance(wholeImage.getSegmentData(), 0, maxPixelVal);
			ImageSegmentDA segment = new ImageSegmentDA(im, i, _localWidth, _localHeight, 0, 0);
			while(segment.get1PixelNextSegment() != null){
				segments.add(segment);
				float[][] pixelArray = segment.getSegmentData();
				float centerPixel = pixelArray[centerX][centerY];
				float localMean = MathUT.getNormalizedMean(pixelArray, maxPixelVal);
				float localVariance = MathUT.getNormalizedVariance(pixelArray, 0, maxPixelVal);
				if((localMean <= getParamMeanUpperLimit() * wholeMean) &&
						(getParamVarianceLowerLimit() * wholeVariance <= localVariance) &&
						(getParamVarianceUpperLimit() * wholeVariance >= localVariance)){
					centerPixel = centerPixel * getParamIntensityMultiplier();
				}             
				pixelArray[centerX][centerY] = centerPixel;
				segment = segment.get1PixelNextSegment();
			}
		}
	    for (Iterator iterator = segments.iterator(); iterator.hasNext();) {
			ImageSegmentDA imageSegmentDA = (ImageSegmentDA) iterator.next();
			imageSegmentDA.writePixel(centerX, centerY);
		}
	    setOutput(new ImageDA(im));
		return getOutput();
		/*
		ImageDA im = new ImageDA(getInputAsImageDA());   
	    int nBand = im.getNBands();
	    for (int i = 0; i < nBand; i++) {
	    	int maxPixelVal = im.getNBins(i) - 1;
	    	int width = im.getWidth();
	    	ImageSegmentDA wholeImage = new ImageSegmentDA(im, i, im.getWidth(), im.getHeight(), 0, 0);
			//ImageSegmentDA segment = new ImageSegmentDA(im, i, 1, height, 0, 0);
			ImageSegmentDA segmentRow = new ImageSegmentDA(im, i, width, 1, 0, 0);		
			int x = 0;
			float[] yData = new float[im.getHeight()];
			while(segmentRow != null){
				float[][] pixelArray = segmentRow.getSegmentData();
				float localVariance = MathUT.getNormalizedVariance(pixelArray, 0, maxPixelVal);
				yData[x] = localVariance;
				pixelArray = segmentRow.getSegmentData();
				localVariance = MathUT.getNormalizedVariance(pixelArray, 0, maxPixelVal);
				System.out.println("Pos = " + x + "Row Variance = " + localVariance);
				x++;
				segmentRow = segmentRow.get1PixelNextSegment();
			}
			float[] xData = MathUT.getIntegerSeries(1, im.getHeight());
			float[] fftMagnitude = MathUT.getComplexMagnitude(MathUT.getFFT(yData));
			DataPlotUT.plot2DXYBar(xData, yData, "Row", "Variance", "Variance");
			DataPlotUT.plot2DXYBar(xData, fftMagnitude, "Row", "FFT Magnitude", "FFT Magnitude");
			
		}
	    System.out.println("View");
	    setOutput(new ImageDA(im));
		return getOutput();
		*/
	}
}